home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1996 June
/
EnigmA AMIGA RUN 08 (1996)(G.R. Edizioni)(IT)[!][issue 1996-06][EARSAN CD VII].iso
/
earcd
/
dtype
/
fontdt12.lha
/
Src
/
dispatch.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-05-06
|
17KB
|
545 lines
/*
** dispatch.c - dispatcher for Font DataType class
** Copyright © 1995-96 Michael Letowski
*/
#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dos.h>
#include <graphics/displayinfo.h>
#include <graphics/gfx.h>
#include <graphics/modeid.h>
#include <graphics/rastport.h>
#include <graphics/text.h>
#include <intuition/classes.h>
#include <datatypes/datatypes.h>
#include <datatypes/datatypesclass.h>
#include <datatypes/pictureclass.h>
#include <diskfont/diskfont.h>
#include <utility/hooks.h>
#include <utility/tagitem.h>
#include <support/types.h>
#include <support/graphics.h>
#include <stdlib.h>
#include <proto/dos.h>
#include <proto/exec.h>
#include <proto/diskfont.h>
#include <proto/datatypes.h>
#include <proto/graphics.h>
#include <proto/intuition.h>
#include <proto/utility.h>
#include <clib/support_protos.h>
#include "classbase.h"
#include "dispatch.h"
#include "prefs.h"
#include "otag.h"
/****** font.datatype/font.datatype *****************************************
*
* NAME
* font.datatype -- data type for Amiga bitmap and outline fonts.
*
* FUNCTION
* The font data type, a sub-class of the picture.datatype, is used
* to load (and display) Amiga bitmap and outline fonts. All available
* sizes of a given font are loaded into memory and then rendered into
* screen, taking user preferences into account.
* By default this data type will render each font size in one line,
* in ascending order. Whole characters set for the given font and size
* will be rendered.
*
* User preferences are stored in font.prefs file, located in either
* PROGDIR:Prefs/DataTypes/ or ENV:DataTypes/ directory (searched in
* that order). A preferences file is an ASCII file parsed with the
* following ReadArgs() template:
*
* STRINGS/M,CENTER=CENTRE/S,INV=INVERSE/S,FN=FONTNAME/S,
* DPI/K,FG=FOREGROUND/K,BG=BACKGROUND/K
*
* STRINGS are multiple texts that are to be rendered instead of the
* default character set. Each string is rendered in one line.
* CENTRE indicates that each line should be centered on screen.
* INVERSE indicates foreground/background color inversion. Does not
* work for color fonts.
* FONTNAME indicates that for each font's size the name and size of
* that font should be rendered before any user text.
* DPI describes font's aspect ratio, in XDPI/A/N,YDPI/A/N format.
* Default values for aspect ratio are DiskFont's defaults.
* FOREGROUND describes foreground color for two-color fonts. The string
* is parsed with R=RED/A/N,G=GREEN/A/N,B=BLUE/A/N template to extract
* red, green and blue components for a given color. Default foreground
* color is black. This option does not work for color fonts.
* BACKGROUND describes background color for two-color fonts. The string
* is parsed with R=RED/A/N,G=GREEN/A/N,B=BLUE/A/N template to extract
* red, green and blue components for a given color. Default background
* color is white. This option does not work for color fonts.
*
* METHODS
* OM_NEW -- Create a new picture object from a .font file and all
* associated size files. The source must be a file.
*
* NOTES
* Since version 39.4 a font to be loaded does not need to be in
* FONTS: path. The data type will temporarily extend FONTS: assign
* to cover given font.
* If bitmaps are created for an outline font, the data type will load
* only those sizes, for which bitmaps exist. Otherwise all DiskFont
* default sizes will be loaded.
* For color fonts the color is set to that of biggest size.
*
* BUGS
* Loading outline fonts with multiple size requires 'a lot' of memory.
* OpenDiskFont() uses a lot of stack and this causes problems with
* small-stack clients like original IPrefs.
*
* SEE ALSO
* picture.datatype, diskfont.library, bullet.library.
*
*****************************************************************************
*
*/
/*
** Private constants
*/
#define IDS_CNT 4 /* Number of ModeIDs */
#define COL_WHITE 0xFF /* 'white' colour */
#define COL_BLACK 0x00 /* 'black' colour */
#define DEF_XDPI 72 /* Default X-axis DPI */
#define DEF_YDPI 80 /* Default Y-axis DPI */
#define FONTSPATH "FONTS" /* Assign name without ':' */
/* 256 for ASCII set, 2 for terminator */
#define MAX_CHAR (256+2)
/* 32 chars for font name, 6 for size, 2 for terminator */
#define MAX_CHAR2 (32+6+2)
/* Total number of strings */
#define MAX_STRING 32
/* Get font's name */
#define FontName(f) ((f)->tf_Message.mn_Node.ln_Name)
/* Convenient cast */
#define CFont(f) ((struct ColorTextFont *)(f))
typedef int (SFUNC)(void const*, void const *);
/*
** Private functions prototypes
*/
STATIC ASM Object *Dispatch(R_A0 Class *cl, R_A2 Object *o, R_A1 Msg msg);
STATIC LBOOL GetFont(struct ClassBase *cb, Object *o, struct TagItem *attrs);
/* Font management */
STATIC struct TextFont **OpenFonts(struct ClassBase *cb, struct Opts *opts,
struct FontContentsHeader *fch, STRPTR name);
STATIC VOID CloseFonts(struct ClassBase *cb, struct TextFont **f, ULONG cnt);
/* Rendering */
STATIC LBOOL GetWH(struct ClassBase *cb, struct RastPort *rp, struct Opts *opt,
struct TextFont *f, ULONG *w, ULONG *h);
STATIC LBOOL Render(struct ClassBase *cb, struct RastPort *rp, struct Opts *opt,
struct TextFont **f, ULONG cnt, ULONG w);
STATIC STRPTR *PrepStrings(struct ClassBase *cb, struct Opts *opt,
struct TextFont *f, ULONG *cnt);
STATIC LONG SortFunc(struct TextFont **tf1, struct TextFont **tf2);
/* DataTypes stubs */
STATIC ULONG LocSetDTAttrs(struct ClassBase *cb, Object *o, ULONG data, ...);
STATIC ULONG LocGetDTAttrs(struct ClassBase *cb, Object *o, ULONG data, ...);
/*
** Public functions
*/
Class *InitClass(struct ClassBase *cb)
{
Class *CL;
/* Create our class (no instance) */
if(CL=MakeClass(DATATYPENAME,SUPERCLASSNAME,NULL,NULL,0))
{
CL->cl_Dispatcher.h_Entry=(HOOKFUNC)Dispatch;
CL->cl_UserData=(ULONG)cb;
AddClass(CL);
}
return(CL);
} /* InitClass */
/*
** Level 1 private functions
*/
STATIC ASM Object *Dispatch(R_A0 Class *cl, R_A2 Object *o, R_A1 Msg msg)
{
struct ClassBase *cb=(struct ClassBase *)cl->cl_UserData;
Object *Obj;
switch(msg->MethodID)
{
case OM_NEW: /* We know this method */
if(Obj=(Object *)DoSuperMethodA(cl,o,msg))
unless(GetFont(cb,Obj,((struct opSet *)msg)->ops_AttrList))
{
CoerceMethod(cl,Obj,OM_DISPOSE);
Obj=NULL;
}
break;
default: /* Let the superclass handle it */
Obj=(Object *)DoSuperMethodA(cl,o,msg);
break;
}
return(Obj);
} /* Dispatch */
/*
** Level 2 private functions
*/
STATIC LBOOL GetFont(struct ClassBase *cb, Object *o, struct TagItem *attrs)
{
STATIC CONST ULONG SourceIDs[IDS_CNT]= /* Font flag->mode selector */
{
LORES_KEY,HIRES_KEY,LORESLACE_KEY,HIRESLACE_KEY
}; /* ModeIDs */
struct RastPort RP;
struct Opts Opts;
struct PrefsHandle *PH;
struct FileInfoBlock *FIB;
struct FontContentsHeader *FCH;
struct TextFont **Fonts=NULL,*F;
struct BitMapHeader *BMHD=NULL;
struct ColorFontColors *CFC;
struct ColorRegister *CMap=NULL;
LONG *CRegs=NULL;
STRPTR Title,Name=NULL; /* Font file name & picture title */
BPTR DirLock,FH=0;
ULONG TallWide,ModeID;
ULONG Width,Height,Depth;
ULONG I,J,NumFonts;
UBYTE ForeCol[3],BackCol[3],TCol;
LBOOL AFlag=FALSE,Result=FALSE;
/* Read preferences */
PH=GetFontPrefs(cb,&Opts);
/* Get default title */
Title=(STRPTR)GetTagData(DTA_Name,NULL,attrs);
/* Get file handle and BitMapHeader */
LocGetDTAttrs(cb,o,DTA_Handle,&FH,PDTA_BitMapHeader,&BMHD,TAG_DONE);
try(FH && BMHD, EXIT);
/* Get font file name */
try(FIB=AllocDosObject(DOS_FIB,NULL), NO_FIB);/* Create FileInfoBlock */
if(ExamineFH(FH,FIB)) /* Examine it */
Name=FIB->fib_FileName; /* Get name pointer */
unless(Name) /* Still no name */
if(Title) /* Use title to get name */
Name=FilePart(Title); /* Get file part of title */
try(Name, NO_NAME);
/* Examine .font file, load sizes */
if(DirLock=ParentOfFH(FH))
{
if(FCH=NewFC(cb,DirLock,Name))
{
AFlag=AssignAdd(FONTSPATH,DirLock);
Fonts=OpenFonts(cb,&Opts,FCH,Name);
NumFonts=FCH->fch_NumEntries;
DisposeFC(cb,FCH);
}
if(AFlag)
RemAssignList(FONTSPATH,DirLock);
else
UnLock(DirLock);
}
try(Fonts, NO_FONTS); /* Check if any fonts loaded */
/* Set colors */
for(I=0; I<3; I++) /* For each of RGB triad */
{
if(Opts.opt_ForeFlag) ForeCol[I]=clamp(Opts.opt_ForeCol[I],0,255);
else ForeCol[I]=COL_BLACK;
if(Opts.opt_BackFlag) BackCol[I]=clamp(Opts.opt_BackCol[I],0,255);
else BackCol[I]=COL_WHITE;
}
/* Calculate sizes */
TallWide=0;
Width=Height=0;
Depth=1;
InitRastPort(&RP); /* Set up RastPort - here! */
for(I=0; I<NumFonts; I++)
if(F=Fonts[I]) /* Opened successfully */
{
try(GetWH(cb,&RP,&Opts,F,&Width,&Height), ERROR);
if(ftst(F->tf_Style,FSF_COLORFONT)) /* This is ColorFont */
if(CFont(F)->ctf_Depth>Depth) /* Deeper? */
Depth=CFont(F)->ctf_Depth; /* Set new depth */
TallWide=(F->tf_Flags & (FPF_TALLDOT | FPF_WIDEDOT))>>FPB_TALLDOT;
}
/* Set up BitMap header */
BMHD->bmh_Width=Width; /* Fill in informations */
BMHD->bmh_Height=Height;
BMHD->bmh_Depth=Depth;
/* Get display mode id */
ModeID=BestModeID(BIDTAG_DesiredWidth, Width,
BIDTAG_DesiredHeight, Height,
BIDTAG_Depth, Depth,
BIDTAG_SourceID, SourceIDs[TallWide & (IDS_CNT-1)],
TAG_DONE);
/* Set colors */
LocSetDTAttrs(cb,o,PDTA_NumColors,1<<Depth,TAG_DONE);
LocGetDTAttrs(cb,o,PDTA_ColorRegisters,&CMap,PDTA_CRegs,&CRegs,TAG_DONE);
try(CMap && CRegs, ERROR);
if(Depth==1) /* B&W font */
{
if(Opts.opt_Inverse) /* Inversion? */
for(I=0; I<3; I++) /* For each of RGB triad */
tswap(ForeCol[I],BackCol[I],TCol); /* Swap foreground/background */
for(I=0; I<3; I++) /* For each of RGB triad */
{
((UBYTE *)&CMap[0])[I]=BackCol[I];
CRegs[I+0]=Color32(BackCol[I]);
((UBYTE *)&CMap[1])[I]=ForeCol[I];
CRegs[I+3]=Color32(ForeCol[I]);
}
}
else /* Some color fonts */
for(I=0; I<NumFonts; I++) /* For each font */
if(F=Fonts[I]) /* Is it valid? */
if(ftst(F->tf_Style,FSF_COLORFONT)) /* Is it color? */
if(CFC=CFont(F)->ctf_ColorFontColors) /* Color table valid? */
for(J=0; J<CFC->cfc_Count; J++) /* Fore each color in table */
{
CMap[J].red= (CFC->cfc_ColorTable[J] & 0x0F00)>>4;
CRegs[J*3+0]= Color32(CMap[J].red);
CMap[J].green= (CFC->cfc_ColorTable[J] & 0x00F0);
CRegs[J*3+1]= Color32(CMap[J].green);
CMap[J].blue= (CFC->cfc_ColorTable[J] & 0x000F)<<4;
CRegs[J*3+2]= Color32(CMap[J].blue);
}
/* Prepare bitmap */
if(RP.BitMap=AllocBitMap(Width,Height,Depth,BMF_CLEAR | BMF_INTERLEAVED,NULL))
{
/* Do rendering */
if(Result=Render(cb,&RP,&Opts,Fonts,NumFonts,Width))
LocSetDTAttrs(cb,o,DTA_ObjName, Title,
DTA_NominalHoriz, Width,
DTA_NominalVert, Height,
PDTA_BitMap, RP.BitMap,
PDTA_ModeID, ModeID,
TAG_DONE);
else /* Could not render */
FreeBitMap(RP.BitMap);
}
/* Cleanup */
catch(ERROR, );
catch(NO_FONTS, CloseFonts(cb,Fonts,NumFonts));
catch(NO_NAME, );
catch(NO_FIB, FreeDosObject(DOS_FIB,FIB)); /* MUST be freed here, not before! */
catch(EXIT, );
if(PH) FreeFontPrefs(cb,PH);
return(Result);
} /* GetFont */
/*
** Font management
*/
STATIC struct TextFont **OpenFonts(struct ClassBase *cb, struct Opts *opts,
struct FontContentsHeader *fch, STRPTR name)
{
struct TagItem MyTags[]=
{
{TA_DeviceDPI, 0},
{TAG_DONE, 0}
}; /* MyTags */
struct TTextAttr TTA;
struct TextFont **Fonts;
struct TFontContents *TFC;
LONG XDPI,YDPI;
ULONG I,NumEntries=fch->fch_NumEntries;
ULONG FCnt=0; /* Number of opened fonts */
try(Fonts=AllocVec(NumEntries*sizeof(APTR),MEMF_CLEAR), NO_FONTS);
for(I=0; I<NumEntries; I++)
{
TFC=&TFontContents(fch)[I]; /* Get FontContents */
TTA.tta_Name=name; /* Copy attrs */
TTA.tta_YSize=TFC->tfc_YSize;
TTA.tta_Style=TFC->tfc_Style;
TTA.tta_Flags=TFC->tfc_Flags | FPF_DISKFONT;
if(ftst(TFC->tfc_Style,FSF_TAGGED)) /* Tags should be set */
TTA.tta_Tags=(struct TagItem *)
&TFC->tfc_FileName
[MAXFONTPATH-(TFC->tfc_TagCount*sizeof(struct TagItem))];
elif(opts->opt_DPIFlag) /* DPI given - set our own DPI tags */
{
XDPI=clamp(opts->opt_XDPI,1,65535);
YDPI=clamp(opts->opt_YDPI,1,65535);
MyTags[0].ti_Data=(XDPI<<16) | YDPI;
TTA.tta_Tags=MyTags;
fset(TTA.tta_Style,FSF_TAGGED);
}
if(Fonts[I]=OpenDiskFont((struct TextAttr *)&TTA))
FCnt++;
}
unless(FCnt) /* No font loaded */
throw2(SetIoErr(ERROR_OBJECT_NOT_FOUND), ERROR);
qsort(Fonts,NumEntries,sizeof(APTR),(SFUNC *)SortFunc);
return(Fonts);
catch(ERROR, );
catch(NO_FONTS, FreeVec(Fonts));
return(NULL);
} /* OpenFonts */
STATIC VOID CloseFonts(struct ClassBase *cb, struct TextFont **f, ULONG cnt)
{
ULONG I;
for(I=0; I<cnt; I++)
if(f[I])
CloseFont(f[I]);
FreeVec(f);
} /* CloseFonts */
/*
** Rendering
*/
STATIC LBOOL GetWH(struct ClassBase *cb, struct RastPort *rp, struct Opts *opt,
struct TextFont *f, ULONG *w, ULONG *h)
{
STRPTR CurStr,*Strs;
ULONG W,J,SCnt;
if(Strs=PrepStrings(cb,opt,f,&SCnt)) /* Allocate and init strings */
{
/* Calculate sizes */
SetFont(rp,f);
for(J=0; J<SCnt; J++)
{
CurStr=Strs[J];
W=TextLength(rp,CurStr,strlen(CurStr)); /* Calculate len of this line */
if(W>*w) /* If larger... */
*w=W; /* Make it new width */
*h+=f->tf_YSize; /* Add to height */
}
FreeVec(Strs); /* Free strings */
}
return(Strs!=NULL);
} /* GetWH */
STATIC LBOOL Render(struct ClassBase *cb, struct RastPort *rp, struct Opts *opt,
struct TextFont **f, ULONG cnt, ULONG w)
{
struct TextFont *F;
STRPTR CurStr,*Strs;
ULONG SCnt,I,J,X,Y=0;
LBOOL Rendered=FALSE;
for(I=0; I<cnt; I++) /* For each font size */
if(F=f[I]) /* Size opened? */
if(Strs=PrepStrings(cb,opt,F,&SCnt)) /* Allocate and init strings */
{
Rendered=TRUE;
/* Do rendering */
SetFont(rp,F); /* Make it a current font */
for(J=0; J<SCnt; J++)
{
CurStr=Strs[J];
X=opt->opt_Center ? (w-TextLength(rp,CurStr,strlen(CurStr)))/2 : 0;
Move(rp,X,Y+F->tf_Baseline);
Text(rp,CurStr,strlen(CurStr));
Y+=F->tf_YSize;
}
FreeVec(Strs); /* Free strings */
}
return(Rendered);
} /* Render */
STATIC STRPTR *PrepStrings(struct ClassBase *cb, struct Opts *opt,
struct TextFont *f, ULONG *cnt)
{
STRPTR S1,S2,CurStr;
STRPTR *Strs,*Ss;
ULONG I,Cnt,Temp;
/* Calculate number of strings */
Cnt=2;
if(Ss=opt->opt_Strings) /* Strings given */
while(CurStr=*Ss++) /* For each string */
if(*CurStr) /* Non-empty string */
Cnt++; /* Increase count */
/* Allocate and fill strings array */
if(Strs=AllocVec(Cnt*sizeof(STRPTR)+MAX_CHAR+MAX_CHAR2,MEMF_CLEAR))
{
S1=(STRPTR)Strs+Cnt*sizeof(STRPTR);
S2=S1+MAX_CHAR;
Cnt=0;
if(opt->opt_FontName && FontName(f)) /* FontName - first */
{
SNPrintf(S2,MAX_CHAR-1,"%s %ld",FontName(f),f->tf_YSize);
Strs[Cnt++]=S2; /* Init strings array */
}
Temp=Cnt;
if(Ss=opt->opt_Strings) /* User's strings given */
while(CurStr=*Ss++) /* While array not filled */
if(*CurStr) /* Non-empty string */
Strs[Cnt++]=CurStr; /* Fill in array */
if(Cnt==0 || !Ss && Cnt==Temp) /* Use charset */
{
for(I=f->tf_LoChar; I<=f->tf_HiChar; I++)
S1[I - f->tf_LoChar]=I ? (CHAR)I : ' '; /* Make ASCII array */
Strs[Cnt++]=S1;
}
*cnt=Cnt;
}
return(Strs);
} /* PrepStrings */
STATIC LONG SortFunc(struct TextFont **tf1, struct TextFont **tf2)
{
if(*tf1 && *tf2) return((LONG)(*tf1)->tf_YSize - (*tf2)->tf_YSize);
else if(*tf1) return(-1);
else if(*tf2) return(1);
else return(0);
} /* SortFunc */
/*
** DataTypes stubs
*/
STATIC ULONG LocSetDTAttrs(struct ClassBase *cb, Object *o, ULONG data, ...)
{
return(SetDTAttrsA(o,NULL,NULL,(struct TagItem *)&data));
} /* LocSetDTAttrs */
STATIC ULONG LocGetDTAttrs(struct ClassBase *cb, Object *o, ULONG data, ...)
{
return(GetDTAttrsA(o,(struct TagItem *)&data));
} /* LocGetDTAttrs */